/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - core/containers
// Copyright( c) 2014.  All Rights Reserved
//
// File:		AEMap.h
// Author:		Gianluca Belardelli
// Date:		20/06/2014
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AEMAP_H_
#define _AEMAP_H_

template <typename KEY, typename VAL=KEY, typename OPS=AEMapOperations<KEY>, typename Allocator=AEContainerHeapAllocator>
class AEMap : public AEBaseMap<KEY,VAL,OPS>
{
// Members
public:
	enum AEInternalInitializer
	{
		UNINITIALIZED,
	};

	typedef AEMap<KEY,VAL,OPS,AEContainerTempAllocator> Temp;
	typedef AEMap<KEY,VAL,OPS,AEContainerDebugAllocator> Debug;
	typedef AEMap<KEY,VAL,OPS,AEContainerHeapAllocator> Heap;

// Methods
public:

	AE_DECLARE_NONVIRTUAL_CLASS_ALLOCATOR( TOBEDEFINED, AEMap );


	///
	AEMap( AEINT32 nElem=0 ) { if ( nElem ){ Reserve( nElem ); } }

	/// Create pointer map initially using preallocated memory block.
	/// Use the getSizeInBytesFor(int numKeys) method to find the buffer size
	/// required for a given number of keys.
	AEMap( void *lpPtr, AEINT32 nSizeInBytes) : AEBaseMap<KEY,VAL,OPS>( lpPtr, nSizeInBytes ) {}

	/// Create an uninitialized map. For internal use.
	AEMap( AEInternalInitializer ii ) : AEBaseMap<KEY,VAL,OPS>( AEBaseMap<KEY,VAL,OPS>::UNINITIALIZED )  {}

	/// Destroy a pointer map.
	~AEMap( void ) { AEBaseMap<KEY, VAL, OPS>::ClearAndDeallocate( Allocator().Get(this) ); }
		
	/// Insert key with associated value val. Keys are unique and by default
	/// (if using hkPointerMapOperations) cannot be -1.
	/// If key already exists it is overwritten.
	AE_FORCEINLINE AEBOOL32 Insert( KEY key, VAL val ) { return AEBaseMap<KEY,VAL,OPS>::Insert(Allocator().Get(this), key, val); }

	/// Insert key with associated value val. Keys are unique and by default
	/// (if using hkPointerMapOperations) cannot be -1.
	/// If key already exists it is overwritten.
	/// res is set to HK_SUCCESS if the insertion succeeded, HK_FAILURE otherwise
	AE_FORCEINLINE AEBOOL32 TryInsert( KEY key, VAL val, AEUINT32 &res ) { return AEBaseMap<KEY,VAL,OPS>::TryInsert( Allocator().Get(this), key, val, res ); }

	/// If key is present return its iterator, else insert (key,val) and return the new iterator.
	/// Thus the returned iterator is always valid.
	AE_FORCEINLINE typename AEBaseMap<KEY,VAL,OPS>::AEMapIterator FindOrInsertKey( KEY key, VAL def ) { return AEBaseMap<KEY,VAL,OPS>::FindOrInsertKey(Allocator().Get(this), key, def ); }

	/// Swap all data with another map.
	void Swap( AEMap &other );

	// Estimates and sets the appropriate table size for a given number of elements.
	AE_FORCEINLINE void Reserve( AEINT32 nNumElements ) { return AEBaseMap<KEY,VAL,OPS>::Reserve(Allocator().Get(this), nNumElements ); }
};

#endif // _AEMAP_H_
